﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Nes.Core.Mappers
{
    internal class Mapper3 : IMapper
    {
        private int chrBankSelect;

        public ICartridge cartridge { get; private set; }
        /// <summary>
        /// 程序数据 [0x8000, 0xffff) 32KB
        /// </summary>
        public Byte[] PRG { get; private set; }
        /// <summary>
        /// 图像数据 [0x0000, 0x2000) 8KB
        /// </summary>
        public Byte[] CHR { get; private set; }
        /// <summary>
        /// 扩展的内存 [0x6000,0x8000) 8KB
        /// </summary>
        public Byte[] SRAM { get; private set; }

        public Boolean IsMirrored { get; private set; }



        public Mapper3(ICartridge cartridge, byte[] sram)
        {
            this.cartridge = cartridge;
            chrBankSelect = 0;
            this.PRG = new Byte[32 * 1024];
            this.CHR = new Byte[32 * 1024];
            Array.Copy(cartridge.PRG, PRG, cartridge.PRG.Length);
            Array.Copy(cartridge.CHR, CHR, cartridge.CHR.Length);
            this.IsMirrored = PRG.Length == 16 * 1024;
            if(cartridge.PRG.Length == 16 * 1024)
            {
                Array.Copy(cartridge.PRG, 0, PRG, cartridge.PRG.Length, cartridge.PRG.Length);
            }
            if (sram.Length == 0)
            {
                SRAM = new Byte[0x2000];
            }
        }

        public void PPUClockHandle(int scanLine, int cycle)
        {
            

        }

        public byte Read(int address)
        {
            address &= 0xFFFF;
            if (address < 0x2000)
            {
                return this.CHR[(this.chrBankSelect << 13) + address];
            }
            else if (address >= 0x8000)
            {
                return this.PRG[address - 0x8000];
            }
            else if (address >= 0x6000)
            {
                return this.SRAM[address - 0x6000];
            }
            else
            {
                return 0;
            }
        }

        public void Write(int address, byte data)
        {
            address &= 0xFFFF;
            if (address < 0x2000)
            {
                this.CHR[(this.chrBankSelect << 13) + address] = data;
            }
            else if (address >= 0x8000)
            {
                this.chrBankSelect = data & 0x03;
            }
            else if (address >= 0x6000)
            {
                this.SRAM[address - 0x6000] = data;
            }
            else
            {
            }
        }
    }
}
